﻿using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CodeBuilder.ViewModel
{
    public class CreateBaseViewModel
    {
        private string tableName;
        private string fileDir;
        public CreateBaseViewModel(string tableName, string fileDir)
        {
            this.tableName = tableName;
            this.fileDir = fileDir;
        }

        public void Run()
        {
            var formatTableName = Helper.GetPascalCase(tableName).Substring(1);
            var fileName = $"BaseViewModel";
            IList<string> contents = new List<string>();
            contents.Add("using CommunityToolkit.Maui.Alerts;");
            contents.Add("using CommunityToolkit.Maui.Core;                                                                      ");
            contents.Add("using CommunityToolkit.Mvvm.ComponentModel;                                                            ");
            contents.Add("using CommunityToolkit.Mvvm.Input;                                                                     ");
            contents.Add("using Hualong.TestWorldPro.Common.Enums;                                                               ");
            contents.Add("using Hualong.TestWorldPro.Dto;                                                                        ");
            contents.Add("using Hualong.TestWorldPro.Services.Navigation;                                                        ");
            contents.Add("using Microsoft.Extensions.Logging;                                                                    ");
            contents.Add("using System.Collections.ObjectModel;                                                                  ");
            contents.Add("                                                                                                       ");
            contents.Add("namespace Hualong.TestWorldPro.ViewModels                                                              ");
            contents.Add("    {                                                                                                  ");
            contents.Add("        public partial class BaseViewModel : ObservableObject, IViewModelBase                          ");
            contents.Add("        {                                                                                              ");
            contents.Add("            private long _isBusy;                                                                      ");
            contents.Add("            public readonly ILogger<BaseViewModel> logger;                                             ");
            contents.Add("                                                                                                       ");
            contents.Add("            public bool IsBusy => Interlocked.Read(ref _isBusy) > 0;                                   ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private bool _isInitialized;                                                               ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string userName = string.Empty;                                                    ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string lblLoginStatus = string.Empty;                                              ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string lblControllerName = string.Empty;                                           ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private ObservableCollection<ProjChannelDto> channels = new();                             ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string channelName = string.Empty;                                                 ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string displayValue = string.Empty;                                                ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string unitName = string.Empty;                                                    ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string displayName = string.Empty;                                                 ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private DateTime createTime;                                                               ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string createUser = string.Empty;                                                  ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private DateTime updateTime;                                                               ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string updateUser = string.Empty;                                                  ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private bool isEnable = false;                                                             ");
            contents.Add("                                                                                                       ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string lblLineState = \"OFFLINE\";                                                   ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private bool isCanView = true;                                                             ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private bool isCanDel = true;                                                              ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private bool isCanEdit = true;                                                             ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private bool isCanAdd = true;                                                              ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private bool isCanCopy = true;                                                             ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private bool isCanOutput = true;                                                           ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string questionTitle = string.Empty;                                               ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string questionMessage = string.Empty;                                             ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string questionAccept = string.Empty;                                              ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string questionCancel = string.Empty;                                              ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private string remark = string.Empty;                                                      ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private bool hasSelected;                                                                  ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private PageModel pageModel = PageModel.None;                                              ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private long id;                                                                           ");
            contents.Add("                                                                                                       ");
            contents.Add("            [ObservableProperty]                                                                       ");
            contents.Add("            private bool isEnabled;                                                                    ");
            contents.Add("                                                                                                       ");
            contents.Add("            public INavigationService NavigationService { get; }                                       ");
            contents.Add("                                                                                                       ");
            contents.Add("            public IAsyncRelayCommand InitializeAsyncCommand { get; }                                  ");
            contents.Add("                                                                                                       ");
            contents.Add("            public BaseViewModel(INavigationService navigationService, ILogger<BaseViewModel> logger)  ");
            contents.Add("            {                                                                                          ");
            contents.Add("                this.NavigationService = navigationService;                                            ");
            contents.Add("                this.logger = logger;                                                                  ");
            contents.Add("                InitializeAsyncCommand =                                                               ");
            contents.Add("                    new AsyncRelayCommand(                                                             ");
            contents.Add("                        async () =>                                                                    ");
            contents.Add("                        {                                                                              ");
            contents.Add("                            await IsBusyFor(InitializeAsync);                                          ");
            contents.Add("                            IsInitialized = true;                                                      ");
            contents.Add("                        },                                                                             ");
            contents.Add("                        AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler);                       ");
            contents.Add("                                                                                                       ");
            contents.Add("            }                                                                                          ");
            contents.Add("                                                                                                       ");
            contents.Add("            public virtual void ApplyQueryAttributes(IDictionary<string, object> query)                ");
            contents.Add("            {                                                                                          ");
            contents.Add("                                                                                                       ");
            contents.Add("            }                                                                                          ");
            contents.Add("                                                                                                       ");
            contents.Add("            public virtual void OnAppearing()                                                          ");
            contents.Add("            {                                                                                          ");
            contents.Add("            }                                                                                          ");
            contents.Add("                                                                                                       ");
            contents.Add("            public virtual void OnDisappearing()                                                       ");
            contents.Add("            {                                                                                          ");
            contents.Add("            }                                                                                          ");
            contents.Add("                                                                                                       ");
            contents.Add("            public event Func<string, Task>? DoDisplayAlert;                                           ");
            contents.Add("                                                                                                       ");
            contents.Add("            public event Func<BaseViewModel, bool, Task>? DoNavigate;                                  ");
            contents.Add("                                                                                                       ");
            contents.Add("            public async Task ShowSnackBar(string message,                                             ");
            contents.Add("            Action? action = null,                                                                     ");
            contents.Add("            string actionButtonText = AlertDefaults.ActionButtonText,                                  ");
            contents.Add("            TimeSpan? duration = null,                                                                 ");
            contents.Add("            SnackbarOptions? visualOptions = null,                                                     ");
            contents.Add("            IView? anchor = null)                                                                      ");
            contents.Add("            {                                                                                          ");
            contents.Add("                var snackBar = new Snackbar                                                            ");
            contents.Add("                {                                                                                      ");
            contents.Add("                    Text = message,                                                                    ");
            contents.Add("                    Action = action,                                                                   ");
            contents.Add("                    ActionButtonText = actionButtonText,                                               ");
            contents.Add("                    Duration = duration ?? TimeSpan.FromSeconds(3),                                    ");
            contents.Add("                    VisualOptions = visualOptions ?? new(),                                            ");
            contents.Add("                    Anchor = anchor                                                                    ");
            contents.Add("                };                                                                                     ");
            contents.Add("                await snackBar.Show();                                                                 ");
            contents.Add("            }                                                                                          ");
            contents.Add("            public async Task ShowToast(string message, TimeSpan timeSpan)                             ");
            contents.Add("            {                                                                                          ");
            contents.Add("                var toast = Toast.Make(message);                                                       ");
            contents.Add("                var cts = new CancellationTokenSource(timeSpan);                                       ");
            contents.Add("                await toast.Show(cts.Token);                                                           ");
            contents.Add("            }                                                                                          ");
            contents.Add("                                                                                                       ");
            contents.Add("            public Task NavigateAsync(BaseViewModel vm, bool showModal = false)                        ");
            contents.Add("            {                                                                                          ");
            contents.Add("                return DoNavigate?.Invoke(vm, showModal) ?? Task.CompletedTask;                        ");
            contents.Add("            }                                                                                          ");
            contents.Add("                                                                                                       ");
            contents.Add("            public virtual Task InitializeAsync()                                                      ");
            contents.Add("            {                                                                                          ");
            contents.Add("                return Task.CompletedTask;                                                             ");
            contents.Add("            }                                                                                          ");
            contents.Add("                                                                                                       ");
            contents.Add("            public async Task IsBusyFor(Func<Task> unitOfWork)                                         ");
            contents.Add("            {");
            contents.Add("                Interlocked.Increment(ref _isBusy);");
            contents.Add("                OnPropertyChanged(nameof(IsBusy));");
            contents.Add("");
            contents.Add("                try");
            contents.Add("                {");
            contents.Add("                    await unitOfWork();");
            contents.Add("                }");
            contents.Add("                catch (Exception ex)");
            contents.Add("                {");
            contents.Add("                    this.logger.LogError(ex.Message, ex);");
            contents.Add("                }");
            contents.Add("                finally");
            contents.Add("                {");
            contents.Add("                    Interlocked.Decrement(ref _isBusy);");
            contents.Add("                    OnPropertyChanged(nameof(IsBusy));");
            contents.Add("                }");
            contents.Add("            }");
            contents.Add("        }");
            contents.Add("    }");

            string filePath = Path.Combine(fileDir, fileName);
            if (!Directory.Exists(filePath))
            {
                Directory.CreateDirectory(filePath);
            }
            filePath = Path.Combine(filePath, $"{fileName}.cs");
            if (File.Exists(filePath))
            { File.Delete(filePath); }
            File.WriteAllLines(filePath, contents, Encoding.UTF8);

            Console.WriteLine($"创建:{filePath} 完成！");
        }
    }
}
